using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;
using NUnit.Framework;

namespace ProjectEuler.Core.Helpers
{
    public static class StringExtensions
    {
        // stolen from:
        // http://stackoverflow.com/questions/228038/best-way-to-reverse-a-string-in-c-2-0
        public static string Reverse(this string text)
        {
            if (text == null) return null;

            char[] array = text.ToCharArray();
            Array.Reverse(array);
            return new string(array);            
        }

        public static string RemoveWhitespace(this string text)
        {
            if(text == null) return null;

            return Regex.Replace(text, @"\s", "");
        }

        public static bool IsPalindrome(this string text)
        {
            return text == text.Reverse();
        }

        public static IEnumerable<string> Atomize(this string text)
        {
            return text.ToCharArray().Select(c => c.ToString());
        }

        public static int SumDigits(this string text)
        {
            return text.Atomize().Sum(a => int.Parse(a));
        }
    }

    [TestFixture]
    public class When_using_string_extensions
    {
        [Test]
        public void Then_the_Reverse_method_should_return_the_exact_backwards_string()
        {
            Assert.AreEqual("LBRAH", "HARBL".Reverse());
        }

        [Test]
        public void Then_the_RemoveWhitespace_method_should_remove_all_whitespace()
        {
            Assert.AreEqual("HARBL", "HAR\nBL\n".RemoveWhitespace());
            Assert.AreEqual("HARBL", "H AR    BL".RemoveWhitespace());
            Assert.AreEqual("HARBL", "HAR\t\tBL".RemoveWhitespace());
            Assert.AreEqual("HARBL", "\tH\nA\rR BL".RemoveWhitespace());
        }

        [Test]
        public void Then_the_IsPalindrome_method_works_on_strings()
        {
            Assert.IsTrue("GOHANGASALAMIIMALASAGNAHOG".IsPalindrome());
        }

        [Test]
        public void Then_the_Atomize_method_breaks_a_single_string_into_an_array_of_single_character_strings()
        {
            Assert.That("harbl".Atomize().SequenceEqual(new List<string> {"h","a","r","b","l"}));
        }
    }
}